﻿// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Data;
using System.Data.Entity;
using System.Threading;
using System.Threading.Tasks;
using Dapper;
using DotNetFramework.CAP.Abstractions;
using DotNetFramework.CAP.Models;
using MySqlConnector;
using IServiceProvider = DotNetFramework.CAP.Core.Ioc.IServiceProvider;

namespace DotNetFramework.CAP.MySql
{
    public class MySqlPublisher : CapPublisherBase, ICallbackPublisher
    {
        private readonly MySqlOptions _options;

        public MySqlPublisher(IServiceProvider provider) : base(provider)
        {
            _options = provider.GetService<MySqlOptions>();
        }

        public async Task PublishCallbackAsync(CapPublishedMessage message)
        {
            await PublishAsyncInternal(message);
        }

        protected override Task ExecuteAsync(CapPublishedMessage message, ICapTransaction transaction,
            CancellationToken cancel = default(CancellationToken))
        {
            if (NotUseTransaction)
            {
                using (var connection = new MySqlConnection(_options.ConnectionString))
                {
                    //避免死锁
                    //await connection.ExecuteAsync(PrepareSql(), message).ConfigureAwait(false);
                    connection.Execute(PrepareSql(), message);
                    return Task.FromResult(true);
                }
            }

            var dbTrans = transaction.DbTransaction as IDbTransaction;
            if (dbTrans == null && transaction.DbTransaction is DbContextTransaction dbContextTrans)
            {
                dbTrans = dbContextTrans.UnderlyingTransaction;
            }

            var conn = dbTrans?.Connection;
            //await conn.ExecuteAsync(PrepareSql(), message, dbTrans).ConfigureAwait(false);
            conn.Execute(PrepareSql(), message, dbTrans);
            return Task.FromResult(true);
        }

        #region private methods

        private string PrepareSql()
        {
            return
                $"INSERT INTO `{_options.TableNamePrefix}.published` (`Id`,`Version`,`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`)" +
                $"VALUES(@Id,'{_options.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";
        }

        #endregion private methods
    }
}